
--注释
--[[
多行注释
--]]

-- lua -v
-- 5.3.5

g=0
g=nil


function mute(...)
    -- local len = select('#',...)
    ;;
    -- ;(print or io.write)('done') --以括号开头的语句，最好显示的在前面加个;以标明这不是上一个语句的继续
end


function vari() 
    print("变量常量")
    assert(type(v)=="nil")
    v=0
    v=v+1
    assert(type(v)=="number")
    v="s"
    assert(type(v)=="string")
    v={}
    assert(type(v)=="table")
    assert(type(type)=="function")

    b=false
    b=not b
    assert(not nil)

    local c="v"
    b,c=c,b
    a=0
    a,b=a+1,a+1 --赋值语句首先让所有的表达式完成运算， 之后再做赋值操作
    assert(b==1)
end


function stri() 
    print("字符串")
    s='s'
    s="s"
    s=[[
        a
        b
        c
    ]]
    assert("2" .. 6 == "26")
    assert("2"+6 == 8.0) 
    assert(#"xx" == 2)
    s="1234"
    s23=string.sub(s,2,-2)
    assert(s23=="23")
    s=string.format("%d",1)
    assert(s[1]==nil)
    local s="2018-08-17"
    function string.split(str, delimiter)
        str = tostring(str)
        delimiter = tostring(delimiter)
        if (delimiter=='') then return false end
        local pos,arr = 0, {}
        -- for each divider found
        for st,sp in function() return string.find(str, delimiter, pos, true) end do
            table.insert(arr, string.sub(str, pos, st - 1))
            pos = sp + 1
        end
        table.insert(arr, string.sub(str, pos))
        return arr
    end
    local ymd=string.split(s,"-")
    assert(ymd[1]=='2018')
    local y,m,d=table.unpack(ymd)
    assert(y=='2018')

end


function coll() 
	print("数组集合")
    t = {}
    t2 = {1,2,3}
    assert(t2[1]==1)
    t3 = {a="1"}
    assert(t3.a=="1")
    t = {k1="1";k2="2";"3","4",[30]=5;["a"]="b";b="c"}
    for k,v in pairs(t) do
        print(k .. " -> " .. v)
    end
    t.k1=nil --删除
    for i,v in ipairs(t) do
        print(i .. " -> " .. v)
    end
    assert(rawlen(t)==2)
    table.remove(t,1)
    -- assert(table.nums(t)==6) table.nums 不可用，原因未知
end


function proc() 
    print("流程控制")
    ;;
    do 
        print()
    end

    if 0 then
        print("0 is true")
    elseif (a==9) then
        assert(1~=1)
    else
        assert(1~=1)
    end


    t= {}
    for i=1,10,2 do
        t[i]=i
    end
    assert(t['none']==nil)

    for i=10,1,-1 do
        if i>=3 then
            goto continue
        end
        if i<=2 then
            break
        end
        ::continue::
        -- print([[end]])
    end

end

function func()
    print("函数")
    a=assert
    a(true)
end

function clas()
    print("类和对象")
    -- $LUA_PATH
    -- package.path
    -- require "module"
    package.path="./lua/?.lua;;" --环境变量中出现的所有 ";;" 都会被替换成默认路径。
    local module = require("module")
    print(module.constant)
end

function erro()
    local function add(a,b)
        error('throw error message',1)
    end
    assert(not pcall(add,10)) 
    -- 在pcall的，第2、3位置返回函数的结果
end

function othe()
    print("其它")
    -- local path = "/usr/local/lua/lib/libluasocket.so"
    -- local f = loadlib(path, "luaopen_socket")
    -- f() -- 真正打开库
    co = coroutine.wrap(
        function(i)
            print(i);
        end
    )
     
    co(1) 

    -- loadstring在lua5.2中已经被弃用了
    -- load
    local v = load('return 10')()
    assert(v==10)
    -- load(chunk, chunkname, mode, env)
    v=load('return v+10',nil,nil,{v=2})()
    assert(v==12)
    v=load('return v>=10',nil,nil,{v=11})()
    assert(v)
    v=load('return v>=10 and x',nil,nil,{v=11})()
    assert(not v)
    x,y=1,2,3
    assert(y==2)

    x=1
    function t()
        x=10
        return 10
    end
    ok,einfo = xpcall(t,debug.traceback)
    assert(ok)
    assert(x==10)

end

function _test_multi_return()
    local function _c()
        return "a","b","c"
    end
    local x=_c()
    assert(x=="a")
end

function _test_table_add_method()
    local t={
        a=1,
        b=1
    }
    function t:m() 
        self.a=3
    end
    t:m()
    assert(t.a==3)
end

function _test_load_func()
    name = "zhang"
    local localname = "hewe"
    local content = [[
        y="a\nbc"
        x=
        math.min(9,
        2,#y)+
        1
        return x
    ]]
    assert(load(content)()==3)
    local content = 'local y="a\\nbc";if not y then y ="abc" end;return #y'
    assert(load(content,nil,nil,{})()==4,"=4")

    local content = [[ return math.min(x,3) ]]
    assert(load(content,nil,nil,{x=2,math=math})()==2)

    local str = "1"
    local int = str 
    int = tonumber(str)
    assert(str ~= int and str+0==int)
end

function _test_clone()
    local clone = function(object)
        local lookup_table = {}
        local function _copy(object)
            if type(object) ~= "table" then
                return object
            elseif lookup_table[object] then
                return lookup_table[object]
            end
            local new_table = {}
            lookup_table[object] = new_table
            for key, value in pairs(object) do
                new_table[_copy(key)] = _copy(value)
            end
            return setmetatable(new_table, getmetatable(object))
        end
        return _copy(object)
    end

    local a={1,2,3}
    local b =clone(a)
    a[1]=4
    assert(b[1]~=a[1])
end

function test()
    print("test\n")
    _test_multi_return()
    _test_table_add_method()
    _test_load_func()
    _test_clone()
end

function main()
	print("Hello, World!\n")
	vari()
	stri()
	coll()
	proc()
	func()
	clas()
    othe()
    erro()
    test()
end

main()